#ifndef __DATA_M__
#define __DATA_M__
#include "util.hpp"
#include "conf.hpp"
#include <pthread.h>
#include <unordered_map>

namespace Cloud
{
    //数据信息
    struct BackUpInfo
    {
        bool pack_flag;//是否压缩标志
        size_t fsize;//文件大小
        time_t atime;//最新访问时间
        time_t mtime;//文件修改时间
        std::string real_path;//真实路径
        std::string pack_path;//压缩包路径
        std::string url;//URL字段

        bool NewBackUpInfo(const std::string &realpath)
        {
            FileUtil file(realpath);
            if(file.Exists() == false)
            {
                std::cout << "NewBackUpInfo: 文件不存在\n";
                return false;
            }
            Config *cfg = Config::GetInstance();
            std::string packdir = cfg->GetPackDir();//获取压缩包存放路径
            std::string packsuffix = cfg->GetPackFileSuffix();//获取压缩包后缀
            std::string download_prefix = cfg->GetDownLoadPrefix();//获取下载前缀
            //填充字段
            pack_flag = false;
            fsize = file.FileSize();
            atime = file.LastAccTime();
            mtime = file.LastModTime();
            real_path = realpath;
            pack_path = packdir + file.FileName() + packsuffix;//压缩包路径+文件名+后缀
            url = download_prefix + file.FileName();
            return true;
        }
    };

    class DataManager
    {
    public:
        DataManager()
        {
            pthread_rwlock_init(&_rwlock, nullptr);
            _backup_file = Cloud::Config::GetInstance()->GetBackUpFile();//获取备份文件的信息
            InitLoad();
        }
        bool Insert(const BackUpInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);//加写锁
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock);//解锁
            Storage();//每次插入新的数据都要进行一次持久化存储
            return true;
        }
        bool UpData(const BackUpInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock);
            Storage();//每次更新都要进行一次持久化存储
            return true;
        }
        bool GetOneByUrl(const std::string &url, BackUpInfo *info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            //url就是key值，所以我们直接使用url进行查找
            auto it = _table.find(url);
            if(it == _table.end())
            {
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            *info = it->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealPath(const std::string &realpath, BackUpInfo *info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for(;  it != _table.end(); ++it)
            {
                if(it->second.real_path == realpath)
                {
                    *info = it->second;
                    pthread_rwlock_unlock(&_rwlock);
                    return true;
                }
            }
            pthread_rwlock_unlock(&_rwlock);
            return false;
        }
        bool GetAll(std::vector<BackUpInfo> *array)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for(; it != _table.end(); ++it)
            {
                array->push_back(it->second);
            }
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool Storage()//持久化存储--每次信息更改都需要进行一次
        {   
            //获取所有数据
            std::vector<BackUpInfo> array;
            GetAll(&array);
            //添加到Json中
            Json::Value root;
            for(int i = 0; i < array.size(); ++i)
            {
                Json::Value item;
                item["pack_flag"] = array[i].pack_flag;
                item["fsize"] = (Json::Int64)array[i].fsize;
                item["atime"] = (Json::Int64)array[i].atime;
                item["mtime"] = (Json::Int64)array[i].mtime;
                item["real_path"] = array[i].real_path;
                item["pack_path"] = array[i].pack_path;
                item["url"] = array[i].url;
                root.append(item);
            }
            //进行序列化
            std::string body;
            if(JsonUtil::Serialize(root, &body) == false)
            {
                std::cout << "Storage, 序列化数据失败\n";
                return false;
            }
            //写入到文件
            FileUtil file(_backup_file);
            if(file.SetContent(body) == false)
            {
                std::cout << "Storage, 持久化数据失败\n";
                return false;
            }
            return true;
        }
        bool InitLoad()//初始化程序运行时从文件中读取数据
        {
            //读取持久化文件
            FileUtil file(_backup_file);
            if(file.Exists() == false)
            {
                std::cout << "InitLoad, 读取时文件不存在\n";
                return false;
            }
            std::string body;
            file.GetContent(&body);
            //反序列化
            Json::Value root;
            if(JsonUtil::UnSerialize(body, &root) == false)
            {
                std::cout << "InitLoad, 反序列化失败\n";
                return false;
            }
            //将反序列化得到的Json对象添加到_table;
            for(int i = 0; i < root.size(); ++i)
            {
                BackUpInfo info;
                info.pack_flag = root[i]["pack_flag"].asBool();
                info.fsize = root[i]["fsize"].asInt64();
                info.atime = root[i]["atime"].asInt64();
                info.mtime = root[i]["mtime"].asInt64();
                info.real_path = root[i]["real_path"].asString();
                info.pack_path = root[i]["pack_path"].asString();
                info.url = root[i]["url"].asString();
                _table[info.url] = info;
            }
            return true;
        }
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock);
        }
    private:
        std::string _backup_file;//备份信息的持久化存储文件
        pthread_rwlock_t _rwlock;//读写锁
        std::unordered_map<std::string, BackUpInfo> _table;//存储结构
    };
    
}

#endif